#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#include "osdep.h"

#include "frames.h"

// Wi-Fi interface
static struct wif * wi = NULL;
static unsigned char wifi_mac[6];

// Packet reception buffer
#define rx_buffer_size 1024
static unsigned char rx_buffer[rx_buffer_size];

// Packet reception information
static struct rx_info rxInfo;

// Packet transmission buffer
#define tx_buffer_size 1024
static unsigned char tx_buffer[tx_buffer_size];

static int wifi_open(const char *interface)
{
	// Attempt to open Wi-Fi interface
	wi = wi_open((char *)interface);

	if (wi==NULL)
	{
		printf("Unable to open interface %s\n", interface);
		return -1;
	}

	// Read the interface's MAC address
	wi_get_mac(wi, wifi_mac);

	return 0;
}

static void wifi_close()
{
	wi_close(wi);
}

static void wifi_print_address(unsigned char* address)
{
	int i;

	for (i=0; i<6; i++)
		printf(i==0?"%02x":":%02x", address[i]);
	printf("\n");
}

static void wifi_send_proberesponse(unsigned char *DA)
{
	BeaconOrProbeResponse* frame = (BeaconOrProbeResponse*)tx_buffer;

	frame->managementFrame.frame.frameType = FRAME_PROBE_RESPONSE << 2;

	// Set SA, BSSID
	memcpy(frame->managementFrame.SA, wifi_mac, 6);
	memcpy(frame->managementFrame.BSSID, wifi_mac, 6);

	// Set DA (destination address)
	memcpy(frame->managementFrame.DA, DA, 6);

	//
	frame->managementFrame.sequenceControl = 0;

	// Set beacon interval to 100ms
	frame->beaconInterval = 100;

	// Send frame
	// wi_write(wi, tx_buffer, );

}

static void wifi_receive_proberequest()
{
	ManagementFrame* frame = (ManagementFrame*)rx_buffer;

	printf("SA: ");
	wifi_print_address(frame->SA);
	printf("DA: ");
	wifi_print_address(frame->DA);
	printf("BSSID: ");
	wifi_print_address(frame->BSSID);

	// Respond to the probe request
	wifi_send_proberesponse(frame->SA);
}

static void wifi_read()
{
	int bytesRead, frameType;

	// Receive a packet from the Wi-Fi interface. This is a non-blocking read.
	bytesRead = wi_read(wi, rx_buffer, rx_buffer_size, &rxInfo);

	// Parse the packet
	if (bytesRead>0)
	{
		frameType = (rx_buffer[0] >> 2);

		switch (frameType)
		{
		case FRAME_PROBE_REQUEST:
			wifi_receive_proberequest();
			break;
		}
	}

}

int main()
{
	// Attempt to open Wi-Fi interface
	if (wifi_open("mon0"))
		return -1;

	printf("Interface open\n");

	// Receive packets
	while (1)
		wifi_read();

	// Close
	wifi_close();

}
